package cn.com.libertymutual.core.security.jwt;

import io.jsonwebtoken.ExpiredJwtException;

import java.io.IOException;
import java.util.Collections;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.UrlPathHelper;

import com.alibaba.fastjson.JSONObject;

/**
@Component
@Order(50)
@WebFilter(filterName="jwtAuthenticationTokenFilter",urlPatterns={"/test/**", "/sale/test/**", "**bob"},displayName="JwtAuthenticationTokenFilter",description="移动端JWT认证")
**/
///////////@Component  20180202
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    private final Logger log = LoggerFactory.getLogger(getClass());

//   / @Autowired
    private UserDetailsService userDetailsService;	//必须要实现这个接口，不实现的话会死掉

    private UrlPathHelper helper;
    
    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Value("${jwt.header}")
    private String tokenHeader;
    
    /*public JwtAuthenticationTokenFilter( String tokenHeader, JwtTokenUtil jwtTokenUtil ) {
    	this.tokenHeader = tokenHeader;
    	this.jwtTokenUtil = jwtTokenUtil;
    	helper = new UrlPathHelper();
    }*/
    
    @Override
	public void initFilterBean() throws ServletException {
    	helper = new UrlPathHelper();
    	
	}

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
    	log.info("访问地址:{}", helper.getLookupPathForRequest(request));
    	

    	if (helper.getLookupPathForRequest(request).startsWith("/nol/") ) {
    		//return;
    	
	        final String requestHeader = request.getHeader(this.tokenHeader);
	
	        String username = null;
	        String authToken = null;
	        if (requestHeader != null && requestHeader.startsWith("Bearer ")) {
	            authToken = requestHeader.substring(7);
	            try {
	                username = jwtTokenUtil.getUsernameFromToken(authToken);
	            } catch (IllegalArgumentException e) {
	                logger.error("an error occured during getting username from token", e);
	            } catch (ExpiredJwtException e) {
	                logger.warn("the token is expired and not valid anymore", e);
	            }
	        } else {
	            logger.warn("couldn't find bearer string, will ignore the header");
	        }
	
	        logger.info("checking authentication for user " + username);
	        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
	
	            // It is not compelling necessary to load the use details from the database. You could also store the information
	            // in the token and read it from it. It's up to you ;)
	            UserDetails userDetails = null;//this.userDetailsService.loadUserByUsername(username);
	
	            // For simple validation it is completely sufficient to just check the token integrity. You don't have to call
	            // the database compellingly. Again it's up to you ;)
	            if (userDetails!=null&&jwtTokenUtil.validateToken(authToken, userDetails)) {
	                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
	                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
	                logger.info("authenticated user " + username + ", setting security context");
	                SecurityContextHolder.getContext().setAuthentication(authentication);
	            }
	        }
	        
    	}
    	else {
    		
    		
    		UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( null, null, Collections.<GrantedAuthority>emptyList());
    		
            /*authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
            logger.info("authenticated user TEST, setting security context");*/
            //SecurityContextHolder.getContext().setAuthentication( authentication );
    	}
    	
      	chain.doFilter(request, response);
        
    }
}